package com.example.generator.utils;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
import com.baomidou.mybatisplus.generator.engine.BeetlTemplateEngine;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import com.example.generator.config.Config;
import com.example.generator.entity.BaseEntity;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: wust
 * @Description:
 * @CreateDate: 2021-05-25 14:50
 * @Version: 1.0
 */

public class CommonUtils {

    //数据源配置
    private static DataSourceConfig dataSourceConfig() {
        return new DataSourceConfig()
                .setDbType(DbType.MYSQL)
                .setUrl(Config.URL)
                .setUsername(Config.USERNAME)
                .setPassword(Config.PASSWORD)
                .setDriverName(Config.DRIVER)
                ;
    }

    // 配置
    private static GlobalConfig globalConfig() {
        return new GlobalConfig()
                .setAuthor(Config.AUTHOR)           //作者名称
                .setOutputDir(Config.outputDir)
                .setFileOverride(true)            //是否覆盖已有文件
                .setOpen(false)                  // 是否打开输出目录
                .setDateType(DateType.ONLY_DATE) // 时间采用java 8，（操作工具类：JavaLib => DateTimeUtils）
                .setEnableCache(false)// XML 二级缓存
                .setBaseResultMap(false)// XML ResultMap
                .setBaseColumnList(false)// XML columList
                .setKotlin(false) //是否生成 kotlin 代码
                .setMapperName(Config.FILE_NAME_DAO) //自定义文件命名，注意 %s 会自动填充表实体属性！
                .setXmlName(Config.FILE_NAME_XML)
                .setServiceName(Config.FILE_NAME_SERVICE)
                .setServiceImplName(Config.FILE_NAME_SERVICE_IMPL)
                .setControllerName(Config.FILE_NAME_CONTROLLER)
                .setSwagger2(Config.SWAGGER_SUPPORT) // model swagger2
                ;
    }

    //实体类配置
    private static StrategyConfig strategyConfig() {
        return new StrategyConfig()
                .setChainModel(true) // 【实体】是否为构建者模型（默认 false）
                .setNaming(NamingStrategy.underline_to_camel)
                .setColumnNaming(NamingStrategy.underline_to_camel)
//                .setSuperEntityClass(BaseEntity.class)
                .setEntityLombokModel(true)
                .setRestControllerStyle(true)
                .setInclude(Config.TABLE_NAME.split(","))      //数据库表名字
                .setControllerMappingHyphenStyle(false)
                .setEntityTableFieldAnnotationEnable(true) //是否生成实体时，生成字段注解,包括@TableName("")
                ;
    }

    // 包信息配置
    private static PackageConfig packageConfig() {
        return new PackageConfig()
                .setModuleName("code")
                .setParent(Config.PACKAGE_PARENT)
//                .setController(Config.PACKAGE_NAME_CONTROLLER)
//                .setEntity(Config.PACKAGE_NAME_MODEL)
//                .setMapper(Config.PACKAGE_NAME_DAO)
//                .setXml(Config.PACKAGE_NAME_XML)
//                .setService(Config.PACKAGE_NAME_SERVICE)
//                .setServiceImpl(Config.PACKAGE_NAME_SERVICE_IMPL)
                ;
    }

    private static InjectionConfig injectionConfig() {
        InjectionConfig injectionConfig = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };
        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
                return Config.projectPath + "/src/main/resources/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        injectionConfig.setFileOutConfigList(focList);
        return injectionConfig;
    }

    private static TemplateConfig templateConfig() {
        TemplateConfig templateConfig = new TemplateConfig();
        //配置自定义输出模板，指定自定义模板路径，注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
        templateConfig.setController("templates/controllerGenerator.java");
        templateConfig.setServiceImpl("templates/serviceImplGenerator.java");
        templateConfig.setMapper("templates/mapperGenerator.java");
        templateConfig.setEntity("templates/entityGenerator.java");
        templateConfig.setXml(null);
        return templateConfig;

    }

    // 获取模板引擎——使用freemarker模板引擎
    private static AbstractTemplateEngine getTemplateEngine() {
        String templateEngine = Config.TEMPLATE_ENGINE;
        switch (templateEngine) {
            case "velocity":
                return new VelocityTemplateEngine();
            case "freemarker":
                return new FreemarkerTemplateEngine();
            case "beetl":
                return new BeetlTemplateEngine();
            default:
                return new VelocityTemplateEngine();
        }
    }

    // 执行器
    public static void execute() {
        GlobalConfig globalConfig = globalConfig();
        DataSourceConfig dataSourceConfig = dataSourceConfig();
        PackageConfig packageConfig = packageConfig();
        StrategyConfig strategyConfig = strategyConfig();
        InjectionConfig injectionConfig = injectionConfig();
        AbstractTemplateEngine templateEngine = getTemplateEngine();
        new AutoGenerator()
                .setGlobalConfig(globalConfig)
                .setDataSource(dataSourceConfig)
                .setStrategy(strategyConfig)
                .setPackageInfo(packageConfig)
                .setTemplateEngine(templateEngine)
                .setCfg(injectionConfig)
                .setTemplate(templateConfig())
                .execute();
    }

}